// TestStudyConsole.cpp : This file contains the 'main' function. Program execution begins and ends there.
//

#include <iostream>
#include <tuple>
#include <type_traits>
#include "Header.h"
#include <vector>


using namespace std;
/////////////////值传递： const修饰传递/////////////////////////////////////////////////////////

void Cpf(int a)/** 函数内部不能修改a的值 [6/17/2020 ZC] */
{
	if (a == 0)
		return;
	std::cout << "a=" << a << endl;
	a--;
	Cpf(a);
	//a++;/** 语法错误，必须是一个可以改变的右值 [6/17/2020 ZC] */
}

void PrintTuple(tuple<int, float, int, float> tupleA)
{
	cout << get<0>(tupleA) << ";" << get<1>(tupleA) << ";" << get<2>(tupleA) << ";" << get<3>(tupleA) << ";\n";
}

//////////////////////////////////////////////////////////////////////////

//int main()
//{
//#pragma region const修饰普通类型的变量
//	{
//		/** 正常写法 [6/17/2020 ZC] */
//		//const int a = 8;
//		/** 这种写法也正确 [6/17/2020 ZC] */
//		/*int const a = 8;
//		std::cout << "a = \n";
//		std::cout << a;*/
//
//		/** 下面两种写法结果一样，有了volatile这个关键字修饰，可以改变const的值 [6/17/2020 ZC] */
//		/*volatile const int a = 7;
//		const volatile int a = 7;*/
//		/** 没有volatile修饰，不能改变const的值 [6/17/2020 ZC] */
//		/*const int a = 7;
//		int *p = (int*)&a;*/
//		/** 没有(int*)强转，将不能赋值给int *p;因为 &a返回的类型是const int *;
//		***而const int *不能强转成int*
//		[6/17/2020 ZC] */
//		//int *p = &a;/** 错误写法 [6/17/2020 ZC] */
//		/**p = 8;
//		std::cout << a;*/
//	}
//#pragma endregion
//
//#pragma region const修饰指针变量
//	/*************************
//	*const 修饰指针指向的内容，则内容为不可变量;
//	*const 修饰指针，则指针为不可变量
//	*const 修饰指针和指针指向的内容，则指针和指针指向的内容都为不可变量
//	**************************/
//	
//	///////////////////////const 修饰指针指向的内容，则内容为不可变量////////////
//	//int a = 8;
//	//const int *p = &a;
//	//std::cout << p;//输出结果：00000008
//	//p = (const int*)9;
//	//std::cout << p;//输出结果：00000009；表明可以对p进行赋值
//	//*p = 9;/** 写法错误：必须是一个可修改的右值 [6/17/2020 ZC] */
//	//////////////////////////////////////////////////////////////////////////
//
//	/////////////////////////const 修饰指针，则指针为不可变量///////////////////
//	//int a = 8;
//	//int * const p = &a;
//	//std::cout << p << " " << *p << "\n";//输出结果：012FFC74 8
//	////p = (const int*)9;/** 写法错误：必须是一个可修改的右值 [6/17/2020 ZC] */
//	//*p = 9;
//	//std::cout << p << " " << *p;//输出结果：012FFC74 9
//	//////////////////////////////////////////////////////////////////////////
//
//	//////////////////////////////////////////////////////////////////////////
//	/*int a = 8;
//	const int* const P = &a;*/
//	//////////////////////////////////////////////////////////////////////////
//
//	/** 小结：const位于*左边，表示修饰的指针指向的值；
//	*const位于*右边，表示修饰的是指针值
//	*心法：左定值，有定向，const修饰不变量
//	[6/17/2020 ZC] */
//	
//#pragma endregion
//
//#pragma region const参数传递和函数返回值
//	/////////////////值传递： const修饰传递/////////////////////////////////////////////////////////
//
//	//////////////////////////////////////////////////////////////////////////
//#pragma endregion
//
//#pragma region c++ Tuple的用法(元组的用法)
////////////////////////////////////////////////////////////////////////////
//	tuple<int, float, int, float> tupleA = make_tuple(1, 2.f, 3, 4.f);
//	tuple<int, float, int, float> tupleB(1,2.f,3,4.f);
//	/** 获取值 [6/17/2020 ZC] */
//	PrintTuple(tupleA);
//
//	/** 修改值 [6/17/2020 ZC] */
//	get<0>(tupleA) = 5;
//	get<1>(tupleA) = 6.f;
//	get<2>(tupleA) = 7;
//	get<3>(tupleA) = 8.f;
//	//PrintTuple(tupleA);
//	/** forward_as_tuple构造Tuple(元组),一个 元组具有右值引用的args对象，适合作为参数传递给函数。 [6/17/2020 ZC] */
//	{
//		////////////////////////错误用法//////////////////////////////////////////////////
//		auto tupleC = forward_as_tuple(0, 1.f, 2, 3.f);
//		get<0>(tupleC) = 2;
//		get<1>(tupleC) = 4.5f;
//		get<2>(tupleC) = 234;
//		get<3>(tupleC) = 22.f;
//		PrintTuple(tupleC);
//		//////////////////////////////////////////////////////////////////////////
//
//		int a = 0;
//		float b = 0.f;
//		int c = 0;
//		float d = 0.1f;
//
//		auto tupleD = forward_as_tuple(a, b, c, d);
//		get<0>(tupleD) = 2;
//		get<1>(tupleD) = 4.5f;
//		get<2>(tupleD) = 234;
//		get<3>(tupleD) = 22.f;
//		PrintTuple(tupleD);
//		cout << a << endl;
//		cout << b << endl;
//		cout << c << endl;
//		cout << d << endl;
//	}
//
//	
//	tuple<int, float, int, float> a(2, 3, 1, 4);
//	/** 获取tuple的数量 [6/17/2020 ZC] */
//	int Num = tuple_size<decltype(a)>::value;
//	cout << "Num = " << Num << endl;
//	/** 获取tuple类型 1表示第二个参数的索引 [6/17/2020 ZC] */
//	tuple_element<1, decltype(a)>::type t = get<1>(a);
//	cout << "t = " << t << endl;
//	/** 拼接元组 [6/17/2020 ZC] */
//	tuple<int, int, int, int> b(2, 3, 1, 4);
//	tuple<int, int, int, int> c(2, 3, 1, 4);
//
//	//拼接
//	auto TT = tuple_cat(a, b, c);
//	/** 打印tuple全部的值 [6/17/2020 ZC] */
//	//PrintfMyTuple(TT);
////////////////////////////////////////////////////////////////////////////
//#pragma endregion
//
//#pragma region 模板元编程
//	//////////////////////////////////////////////////////////////////////////
//	/*模板元编程产生的源程序是在编译期执行的程序，因此它首先要遵循C++和模板的语法，
//	但是它操作的对象不是运行时普通的变量，
//	因此不能使用运行时的C++关键字（如if、else、for），
//	可用的语法元素相当有限，最常用的是：
//
//		enum、static const，用来定义编译期的整数常量；
//		typedef / using，用于定义元数据；
//		T、Args...，声明元数据类型；
//		template，主要用于定义元函数；
//		"::"，域运算符，用于解析类型作用域获取计算结果（元数据）。
//		如果模板元编程中需要if - else、for等逻辑时该怎么办呢？
//
//		模板元中的if - else可以通过type_traits来实现，它不仅仅可以在编译期做判断，还可以做计算、查询、转换和选择。
//
//		模板元中的for等逻辑可以通过递归、重载、和模板特化（偏特化）等方法实现。*/
//	//////////////////////////////////////////////////////////////////////////
//	cout << "int: " << is_const<int>::value << endl;/** 打印值：0 [6/17/2020 ZC] */
//	cout << "const int: " << is_const<const int>::value << endl;/** 打印值：1 [6/17/2020 ZC] */
//
//	/** 判断类型是否相同 [6/17/2020 ZC] */
//	cout << is_same<int, int>::value << endl;/** 打印值：1 [6/17/2020 ZC] */
//	cout << is_same<int, unsigned int>::value << endl;/** 打印值：0 [6/17/2020 ZC] */
//
//	/** 添加、移除const [6/17/2020 ZC] */
//	cout << is_same<const int, add_const<int>::type>::value << endl;/** 打印值：1 [6/17/2020 ZC] */
//	cout << is_same<const int, remove_const<const int>::type>::value << endl;/** 打印值：0 [6/17/2020 ZC] */
//	/** 添加引用 [6/17/2020 ZC] */
//	cout << is_same<int&, add_lvalue_reference<int>::type>::value << endl;/** 打印值：1 [6/17/2020 ZC] */
//	cout << is_same<int&&, add_rvalue_reference<int>::type>::value << endl;/** 打印值：1 [6/17/2020 ZC] */
//
//	/** 取公共类型 [6/17/2020 ZC] */
//	typedef common_type<unsigned char, short, int>::type NumericType;
//	cout << is_same<int, NumericType>::value << endl;/** 打印值：1 [6/17/2020 ZC] */
//	cout << is_same<string, NumericType>::value << endl;/** 打印值：0 [6/17/2020 ZC] */
//
//	/** type_traits还提供了编译期选择traits：std::conditional，
//	它在编译期根据一个判断式选择两个类型中的一个，和条件表达式的语义类似，类似于一个三元表达式 [6/17/2020 ZC] */
//	typedef conditional<true, int, float>::type TypeA; /** TypeA 相当于int [6/17/2020 ZC] */
//	typedef conditional<false, int, float>::type TypeB;/** TypeB 相当于float [6/17/2020 ZC] */
//	typedef conditional < sizeof(long long) >= sizeof(long double),
//		long long, long double > ::type TypeC;
//	cout << sizeof(long long)<< endl;/** 打印值：8  [6/17/2020 ZC] */
//	cout << sizeof(long double) << endl;/** 打印值：8  [6/17/2020 ZC] */
//	cout << typeid(TypeC).name() << endl;/** 打印值：long long  [6/17/2020 ZC] */
//
//	/** std::decay的基本用法它对于普通类型来说std::decay（朽化）是移除引用和cv符，
//	大大简化了我们的书写。除了普通类型之外，std::decay还可以用于数组和函数，
//	具体的转换规则是这样的：
//　　先移除T类型的引用，得到类型U，U定义为remove_reference<T>::type。 [6/18/2020 ZC] */
//
//	/** 对于普通类型来说std::decay（朽化）是移除引用 [6/18/2020 ZC] */
//	typedef decay<int>::type A;/** int [6/18/2020 ZC] */
//	typedef decay<int&>::type B;/** int [6/18/2020 ZC] */
//	typedef decay<int&&>::type C;/** int [6/18/2020 ZC] */
//	//////////////////////////////////////////////////////////////////////////
//
//	/** 对于普通类型来说std::decay（朽化）是移除cv符 [6/18/2020 ZC] */
//	typedef decay<const int&>::type D;/** int [6/18/2020 ZC] */
//	typedef decay<volatile int&>::type E;/** int [6/18/2020 ZC] */
//
//	typedef decay<int[2]>::type F;/** int* [6/18/2020 ZC] */
//	/** __cdecl 是 C/C++、MFC 默认的调用函数规则
//	*__stdcall 是StandardCall的缩写，是C++的标准调用方式
//	[6/18/2020 ZC] */
//	typedef decay<int(int)>::type G;/** int (__cdecl*)(int) [6/18/2020 ZC] */
//	cout << typeid(G).name() << endl;
//	//////////////////////////////////////////////////////////////////////////
//
//	cout << int() << endl;/** 0 [6/19/2020 ZC] */
//
//	/** type_traits还提供了获取 可调用对象返回类型 的元函数：std::result_of [6/19/2020 ZC] */
//	typedef result_of<decltype(fn)& (int)>::type A1;/** int [6/19/2020 ZC] */
//	typedef result_of<fn_ref(int)>::type B1;/** int [6/19/2020 ZC] */
//	typedef result_of<fn_ptr(int)>::type C1;/** int [6/19/2020 ZC] */
//	typedef result_of<fn_class(int)>::type D1;/** int [6/19/2020 ZC] */
//
//	/** type_traits还提供了一个很有用的元函数std::enable_if
//　	 根据enable_if的字面意思就可以知道，它使得函数在判断条件B仅仅为true时才有效
//	[6/19/2020 ZC] */
//	auto r = foo(1);
//	auto r1 = foo(1.2);
//	//auto r2 = foo("zz");/** foo没有参数列表与foo(const char[3])相匹配 [6/19/2020 ZC] */
//	cout << r << " " << r1 << endl;
//
//	/** 在上面的例子中对模板参数T做了限定，即只能是arithmetic（整型和浮点型）类型，
//	如果为非arithmetic类型，则编译不通过，
//	因为std::enable_if只对满足判断式条件的函数有效，对其他函数无效 [6/19/2020 ZC] */
//
//	/** 可以通过enable_if来实现编译期的if-else逻辑 [6/19/2020 ZC] */
//	auto r2 = fool(4);
//	auto r3 = fool("test");
//	cout << r2 << " " << r3 << endl;
//
//	/** 这个IntegerMax的实现用到了type_traits中的std::integral_const，
//	它在展开参数包的过程中，不断的比较，直到所有的参数都比较完，
//	最终std::integral_const的value值即为最大值。 [6/19/2020 ZC] */
//	cout << IntegerMax<2, 5, 6, 8, 0>::value << endl;/** 8 [6/19/2020 ZC] */
//
//	//cout << MaxAlign<int, short, double, char>::value << endl;/** 8 [6/19/2020 ZC] */
//	//cout << Contains<int, char, double, short>::value << endl;/** 0 [6/19/2020 ZC] */
//	//cout << Contains<int, char, double, int, short>::value << endl;/** 1 [6/19/2020 ZC] */
//	//cout << IndexOf<int, double, short, char, int, float>::value << endl;/** 3 [6/19/2020 ZC] */
//	cout << IndexOf<int, double>::value << endl;/** 3 [6/19/2020 ZC] */
//#pragma endregion
//
//#pragma region 递归调用
//	//Cpf(5);
//#pragma endregion
//
//}

// Run program: Ctrl + F5 or Debug > Start Without Debugging menu
// Debug program: F5 or Debug > Start Debugging menu

// Tips for Getting Started: 
//   1. Use the Solution Explorer window to add/manage files
//   2. Use the Team Explorer window to connect to source control
//   3. Use the Output window to see build output and other messages
//   4. Use the Error List window to view errors
//   5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project
//   6. In the future, to open this project again, go to File > Open > Project and select the .sln file




//class A
//{
//public:
//	A() { std::cout << "Constructor" << std::endl; }
//	A(const A&) { std::cout << "Copy Constructor" << std::endl; }
//	A(const A&&) { std::cout << "Move Constructor" << std::endl; }
//	~A() {}
//};

//static A getA()
//{
//	A a;
//	return a;
//}

class B
{
public:
	B() {}
	B(const B&) { std::cout << "B Constructor" << std::endl; }
};

class A
{
public:
	A() : m_b(new B()) { std::cout << "A Constructor" << std::endl; }
	A(const A& src) :
		m_b(new B(*(src.m_b)))
	{
		std::cout << "A Copy Constructor" << std::endl;
	}
	A(A&& src) noexcept :
		m_b(src.m_b)
	{
		src.m_b = nullptr;
		std::cout << "A Move Constructor" << std::endl;
	}
	~A() { delete m_b; }

private:
	B* m_b;
};

static A getA()
{
	A a;
	std::cout << "================================================" << std::endl;
	return a;
}

class B
{
public:
	const int* GetT() {
		return t;
	}
private:
	int t[3] = { 1,2,3 };
};


int main()
{
	/** 当Move Constructor存在时，调用的时Move Constructor；否则调用的
		时复制构造函数【复制构造函数和构造函数消耗都比较大】，可以通过移动
		构造函数节约性能
	[7/22/2020 ZC] */
	//A a = getA();

	//A a = getA();
	//std::cout << "================================================" << std::endl;
	//A a1(a);
	//std::cout << "================================================" << std::endl;
	///*A a2(std::move(a));*/
	//A a2 = std::move(a);

	/*B b;
	const int* x = b.GetT();*/


	return 0;
}